package com.hitqz.robot.biz.schedule;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.hitqz.robot.api.business.entity.PatrolResultEntity;
import com.hitqz.robot.api.common.entity.BatteryDataInfo;
import com.hitqz.robot.api.common.entity.SysWarning;
import com.hitqz.robot.api.common.entity.Tickets;
import com.hitqz.robot.api.common.entity.TicketsTask;
import com.hitqz.robot.biz.core.FileProperties;
import com.hitqz.robot.biz.core.PatrolProperties;
import com.hitqz.robot.biz.service.*;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;
import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.DecimalFormat;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;

@Component
@Slf4j
@AllArgsConstructor
public class DeleteSchedule {
    private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00");
    private final  FileProperties fileProperties;
    private final PatrolProperties patrolProperties;
    private final PatrolResultService patrolResultService;
    private final SysWarningService sysWarningService;
    private final TicketsService ticketsService;
    private final TicketsTaskService ticketsTaskService;
    private final ExecutorService customThreadPool;
    private final BatteryDataInfoService batteryDataInfoService;
    private final DataSource dataSource;


    private final List<String> backupTables = List.of("form_config",
            "form_field_config", "patrol_check_type", "patrol_dev", "patrol_item", "patrol_item_mark",
            "patrol_object", "patrol_object_standard", "patrol_pose", "patrol_pose_group",
            "robot", "robot_config", "robot_equipment", "robot_equipment_pose", "robot_map", "robot_map_pos",
            "sys_menu", "sys_role", "sys_role_menu", "button"
            );


    @Scheduled(cron = "0 10 * * * ?")
    private void backupH2Table() {
        CompletableFuture.runAsync(() -> {
            // 使用 try-with-resources 确保资源正确关闭
            try (Connection connection = dataSource.getConnection();
                 Statement statement = connection.createStatement()) {
                for (String tableName : backupTables) {
                    // 构造路径时，先使用File.separator，最后再统一替换，避免双斜杠问题
                    String basePath = fileProperties.getLocal().getBasePath();
                    String backupDateDir = DateUtil.format(DateUtil.date(), "yyyyMMdd");
                    String fileName = DateUtil.format(DateUtil.date(), "HH") + "_" + tableName + ".sql";

                    File backupDir = new File(basePath, "backup" + File.separator + backupDateDir);
                    File backupFile = new File(backupDir, fileName);

                    // 确保备份目录存在
                    FileUtil.mkdir(backupDir);

                    // 获取规范化的路径并替换为正斜杠，以兼容H2的SQL语法
                    String filePath = backupFile.getCanonicalPath().replace('\\', '/');

                    // 修正H2的SCRIPT语法：SCRIPT TO '...' TABLE ...
                    String sql = String.format("SCRIPT TO '%s' TABLE %s", filePath, tableName);

                    try {
                        statement.execute(sql);
                        log.info("表 [{}] 备份成功, 路径: {}", tableName, filePath);
                    } catch (Exception e) {
                        // 记录更详细的错误信息，包括SQL语句
                        log.error("表 [{}] 备份失败. SQL: [{}].", tableName, sql, e);
                    }
                }
            } catch (SQLException e) {
                log.error("获取数据库连接失败或在备份过程中发生SQL错误.", e);
            } catch (Exception e) {
                // 添加了对路径处理可能抛出的IOException的捕获
                log.error("备份H2表时发生未知异常.", e);
            }
        }, customThreadPool);
    }


    @Scheduled(cron = "0 0 * * * ?")
    private void deleteBatteryDataInfo(){
        CompletableFuture.runAsync(()->{
            List<BatteryDataInfo> list = batteryDataInfoService.list(Wrappers.<BatteryDataInfo>lambdaQuery().le(BatteryDataInfo::getStatisticalTime, DateUtil.offset(DateUtil.date(), DateField.DAY_OF_YEAR, -patrolProperties.getMaxHistory())));
            if (!list.isEmpty()){
                batteryDataInfoService.removeBatchByIds(list);
                log.info("定期删除电池记录");
            }
        },customThreadPool);
    }


    @Scheduled(cron = "0 0 * * * ?")
    private void deleteWarning(){
        CompletableFuture.runAsync(()->{
            List<SysWarning> list = sysWarningService.list(Wrappers.<SysWarning>lambdaQuery().le(SysWarning::getWarningTime, DateUtil.offset(DateUtil.date(), DateField.DAY_OF_YEAR, -patrolProperties.getMaxHistory())));
            if (!list.isEmpty()){
                sysWarningService.removeBatchByIds(list);
                log.info("定期删除告警记录");
            }
        },customThreadPool);
    }



    @Scheduled(cron = "0 0 * * * ?")
    private void deleteTicketsAndPatrolResult(){
        CompletableFuture.runAsync(()->{
            try {
                String basePath = fileProperties.getLocal().getBasePath();
                File patrolDir = new File(basePath + File.separator + "patrol");
                File visionDir = new File(basePath + File.separator + "vision_draw");
                File excelDir = new File(basePath + File.separator + "excel");
                File backupDir = new File(basePath + File.separator + "backup");
                // 查看文件大小
                long fileSize = 0L;
                if (FileUtil.exist(patrolDir)) {
                    fileSize += FileUtil.size(patrolDir);
                }
                if (FileUtil.exist(visionDir)) {
                    fileSize += FileUtil.size(visionDir);
                }
                if (FileUtil.exist(excelDir)) {
                    fileSize += FileUtil.size(excelDir);
                }
                log.info("当前文件大小为:{} G,限制保存文件大小:{} G", fileSize / 1024 / 1024 / 1024, patrolProperties.getMaxSize());
                if ((fileSize / 1024 / 1024 / 1024) > patrolProperties.getMaxSize()) {
                    log.info("文件大小超过限制,开始删除");
                    DateTime offset = DateUtil.offset(DateUtil.date(), DateField.DAY_OF_YEAR, -patrolProperties.getMaxHistory());
                    List<Tickets> list = ticketsService.list(Wrappers.<Tickets>lambdaQuery().le(Tickets::getCreateTime, offset));
                    if (!list.isEmpty()) {
                        List<Long> idList = list.stream().map(Tickets::getId).toList();
                        ticketsTaskService.remove(Wrappers.<TicketsTask>lambdaQuery().in(TicketsTask::getTicketsId, idList));
                        patrolResultService.remove(Wrappers.<PatrolResultEntity>lambdaQuery().in(PatrolResultEntity::getTicketsId, idList));
                        ticketsService.removeBatchByIds(list);
                        //删除巡检文件
                        deleteOldFiles(patrolDir, offset.getTime());
                        //删除视觉返回图片
                        deleteOldFiles(visionDir, offset.getTime());
                        //删除excel文件
                        deleteOldFiles(excelDir, offset.getTime());
                        //删除sql备份
                        deleteOldFiles(backupDir, offset.getTime());
                        log.info("定期删除文件成功");
                    }
                }
                log.info("定期检测结果和文件");
            }catch (Exception e){
                log.error("定期删除文件异常", e);
            }
        },customThreadPool);
    }


    public static void deleteOldFiles(File folder, long cutoffTime) {
        File[] files = folder.listFiles();
        if (files == null) return;
        for (File file : files) {
            if (file.isDirectory()) {
                deleteOldFiles(file, cutoffTime); // 递归处理子文件夹
                if (FileUtil.isDirEmpty(file)) { // 删除空文件夹
                    FileUtil.del(file);
                }
            } else {
                if (file.lastModified() < cutoffTime) { // 判断文件修改时间
                    FileUtil.del(file);
                }
            }
        }
    }



}
